//
//  ISRingServer.m
//  iPhoneSafety
//
//  Created by dlon 2019/1/2.
//  Copyright © 2019年 com.li.ding. All rights reserved.
//

#import "ISRingServer.h"
#import <AudioToolbox/AudioToolbox.h>
#import <libextobjc/EXTScope.h>
#import "NWLazyProperty.h"
#import <AVFoundation/AVFoundation.h>
#import "ISSafetyAlarmMailManager.h"
#import "ISSafetyAlarmCameraManager.h"
#import "ISSafetyLocalNotificationManager.h"

@implementation ISSoundInfomation

#pragma mark - NSCoding

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.soundName forKey:@"soundName"];
}

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        self.soundName = [aDecoder decodeObjectForKey:@"soundName"];
    }
    return self;
}

@end


@implementation ISRingServerConfig

- (void)save {
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self];
    [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"kISRingServerConfig"];
}

+ (instancetype)serverConfig {
    NSData *configData = [[NSUserDefaults standardUserDefaults] objectForKey:@"kISRingServerConfig"];
    ISRingServerConfig *config = [NSKeyedUnarchiver unarchiveObjectWithData:configData];
    if (!config) {
        config = [ISRingServerConfig new];
        config.voice = 1.f;
        config.shock = NO;
    }
    return config;
}

#pragma mark - NSCoding

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.nowInfo forKey:@"nowInfo"];
    [aCoder encodeDouble:self.voice forKey:@"voice"];
    [aCoder encodeBool:self.shock forKey:@"shock"];
    [aCoder encodeInteger:self.delayTime forKey:@"delayTime"];
    [aCoder encodeInteger:self.wordTime forKey:@"wordTime"];
    [aCoder encodeBool:self.wordOn forKey:@"wordOn"];
    [aCoder encodeObject:self.word forKey:@"word"];
}

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        _nowInfo = [aDecoder decodeObjectForKey:@"nowInfo"];
        _voice = [aDecoder decodeDoubleForKey:@"voice"];
        _shock = [aDecoder decodeBoolForKey:@"shock"];
        _delayTime = [aDecoder decodeIntegerForKey:@"delayTime"];
        
        _wordTime = [aDecoder decodeIntegerForKey:@"wordTime"];
        _word = [aDecoder decodeObjectForKey:@"word"];
        _wordOn = [aDecoder decodeBoolForKey:@"wordOn"];
    }
    return self;
}

#pragma mark - set & get

- (void)setNowInfo:(ISSoundInfomation *)nowInfo {
    _nowInfo = nowInfo;
    [self save];
}

- (void)setVoice:(double)voice {
    _voice = voice;
    [self save];
}

- (void)setShock:(BOOL)shock {
    _shock = shock;
    [self save];
}

- (void)setDelayTime:(NSInteger)delayTime {
    _delayTime = delayTime;
    [self save];
}

- (void)setWordTime:(NSInteger)wordTime {
    _wordTime = wordTime;
    [self save];
}

- (void)setWordOn:(BOOL)wordOn {
    _wordOn = wordOn;
    [self save];
}

- (void)setWord:(NSString *)word {
    _word = word;
    [self save];
}

@end

@interface ISRingServer()

@property (nonatomic, strong, readwrite) NSMutableArray *systemSounds;
@property (nonatomic, strong, readwrite) ISRingServerConfig *config;
@property (nonatomic, strong) AVAudioPlayer *ringPlayer;
@property (nonatomic, assign) BOOL isRing;
@end

@implementation ISRingServer

void soundCompleteCallback(SystemSoundID sound,void *clientData) {
    AudioServicesPlaySystemSound(sound);
}

+ (void)load {
    [ISRingServer shareInstance];
}

+ (instancetype)shareInstance {
    static dispatch_once_t onceToken;
    static ISRingServer *server = nil;
    dispatch_once(&onceToken, ^{
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
        [[AVAudioSession sharedInstance] setActive: YES error: nil];
        
        server = [ISRingServer new];
        [server loadLocalRings];
        [server loadConfig];
        if (!server.config.nowInfo) {
            server.config.nowInfo = server.systemSounds.firstObject;
        } else {
            for (ISSoundInfomation *info in server.systemSounds) {
                if ([info.soundName isEqualToString:server.config.nowInfo.soundName]) {
                    server.config.nowInfo = info;
                }
            }
        }
    });
    return server;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ring:) name:kISSafetyAlarmStateAlarmingNotification object:nil];
    }
    return self;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - private

- (void)loadLocalRings {
    [self.systemSounds removeAllObjects];
    for (int i = 1; i <= 8; i ++) {
        ISSoundInfomation *info = [ISSoundInfomation new];
        info.soundName = [NSString stringWithFormat:@"Alert%d",i];
        info.soundUrl = [[NSBundle mainBundle] URLForResource:info.soundName withExtension:@"mp3"];
        [self.systemSounds addObject:info];
    }
}

- (void)loadConfig {
    self.config = [ISRingServerConfig serverConfig];
}

#pragma mark - public
- (void)ring:(NSNotification *)noti {
    if (self.isRing) {
        return;
    }
    self.isRing = YES;
    @weakify(self)
    [self bk_performBlock:^(id obj) {
        @strongify(self)
        ISSafetyAlarmStrategy strategy = [noti.object unsignedIntegerValue];
        [[ISSafetyLocalNotificationManager sharedInstance] postLocalNotiWithStrategy:strategy];
        [self playWithSound:self.config.nowInfo];
        NSInteger triggerType = [[[NSUserDefaults standardUserDefaults] valueForKey:@"kISSafetyAlarmMailSendType"] integerValue];
        if (triggerType == 0 && [ISSafetyAlarmMailManager sharedInstance].isTakePhotoOn) {
            [[ISSafetyAlarmCameraManager sharedInstance] takePhotoWithCompletion:^(UIImage * _Nonnull image) {
                [[ISSafetyAlarmMailManager sharedInstance] sendMailWithmage:image completion:^(BOOL success, NSError * _Nullable error) {
                    
                }];
            }];
        }
    } afterDelay:self.config.delayTime];
}

- (void)stopRing {
    [self stop];
    self.isRing = NO;
}

- (void)selectSound:(ISSoundInfomation *)sound {
    [self stop];
    self.config.nowInfo = sound;
}

- (void)playWithSound:(ISSoundInfomation *)sound {

    
    [self stop];
    
    self.ringPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:sound.soundUrl error:nil];
    self.ringPlayer.volume = self.config.voice;
    self.ringPlayer.numberOfLoops = -1;
    
    if (self.config.shock) {
        AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate, NULL, NULL, soundCompleteCallback, NULL);
        soundCompleteCallback(kSystemSoundID_Vibrate, NULL);
    }
    
    [self.ringPlayer play];
}

- (void)stop {
    [self.ringPlayer stop];
    self.ringPlayer = nil;
    
    AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate);
    AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate);
}

#pragma mark - set & get

NWLazyPropertyWithInit(NSMutableArray, systemSounds, {
    
})




@end
